package com.dropTables.TakingNote;

import android.app.ListActivity;
import android.app.AlarmManager;
import android.content.Intent;
import android.app.PendingIntent;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.Toast;

import java.sql.Timestamp;
import java.util.Calendar;
import java.util.regex.*;
import java.util.ArrayList;

public class NormalNoteActivity extends ListActivity
{
	private static final int ACTIVITY_CREATE=0;
	private static final int ACTIVITY_EDIT=1;
	private static final int ACTIVITY_MAP = 2;
	private static final int INSERT_ID = Menu.FIRST;
	private static final int GET_ID = Menu.FIRST +1;
	private static final int DELETE_ID = Menu.FIRST + 2;
	private static final int LOGOUT_ID = Menu.FIRST + 3;
	
	public static final String KEY_LIST_STRING = "loc_list";
	public static final String KEY_SELECTED_LOC = "selected_loc";
	public static final String KEY_SELECTED_NAME = "selected_name";
	private static String addSLoc;

	private ReminderDbHelper rDbHelper;
	private Cursor rNotesCursor;
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.reminder_list);
		rDbHelper = new ReminderDbHelper(this);
		rDbHelper.open();
		fillData();
		registerForContextMenu(getListView());
		retrieveItems();

	}
	private void fillData() 
	{
		rNotesCursor = rDbHelper.fetchAllReminders();
		startManagingCursor(rNotesCursor);

		// Create an array to specify the fields we want to display in the list (only TITLE)
		String[] from = new String[]{ReminderDbHelper.KEY_TITLE};

		// and an array of the fields we want to bind those fields to (in this case just text1)
		int[] to = new int[]{R.id.text1};

		// Now create a simple cursor adapter and set it to display
		SimpleCursorAdapter reminders = new SimpleCursorAdapter(this, R.layout.reminder_row, rNotesCursor, from, to);
		setListAdapter(reminders);

	}
	private void createReminder() 
	{
		Intent i = new Intent(this, NoteEditActivity.class);
		startActivityForResult(i,ACTIVITY_CREATE);
	}
	@Override
	public boolean onCreateOptionsMenu(Menu menu) 
	{
		boolean result = super.onCreateOptionsMenu(menu);
		menu.add(0, INSERT_ID, 0, R.string.menu_insert);
		menu.add(0, GET_ID, 0, R.string.menu_get);
		menu.add(0, LOGOUT_ID, 0, R.string.logout);
		return result;
	}
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) 
	{
		super.onListItemClick(l, v, position, id);
		Cursor c = rNotesCursor;
		c.moveToPosition(position);
		Intent i = new Intent(this, NoteEditActivity.class);
		Calendar t = Calendar.getInstance();
		long set_time = c.getLong(c.getColumnIndexOrThrow(ReminderDbHelper.KEY_TIME) ) ;
		t.setTimeInMillis(set_time);
		i.putExtra(ReminderDbHelper.KEY_ROWID, id);
		i.putExtra(ReminderDbHelper.KEY_TITLE, c.getString(c.getColumnIndexOrThrow(ReminderDbHelper.KEY_TITLE)));
		i.putExtra(ReminderDbHelper.KEY_BODY,  c.getString(c.getColumnIndexOrThrow(ReminderDbHelper.KEY_BODY)));
		i.putExtra(ReminderDbHelper.KEY_G_LOC, c.getString(c.getColumnIndexOrThrow(ReminderDbHelper.KEY_G_LOC)));
		i.putExtra(ReminderDbHelper.KEY_S_LOC, c.getString(c.getColumnIndexOrThrow(ReminderDbHelper.KEY_S_LOC)));
		i.putExtra(ReminderDbHelper.KEY_R_ID, c.getLong(c.getColumnIndexOrThrow(ReminderDbHelper.KEY_R_ID)));
		if(set_time>0)
		{
			i.putExtra("hour", t.get(Calendar.HOUR));
			i.putExtra("min",t.get(Calendar.MINUTE));
			i.putExtra("year",t.get(Calendar.YEAR));
			i.putExtra("month",t.get(Calendar.MONTH));
			i.putExtra("day",t.get(Calendar.DATE));
		}
		startActivityForResult(i, ACTIVITY_EDIT);
	}
	//Separates in into the different parts sent by the server, also removes separating : from in
	public ArrayList<String> parseServerInput(String in)
	{
		String time = "";
		Pattern p = Pattern.compile(".*?(?<!:):(?!:)");
		Matcher m = p.matcher(in);
		ArrayList<String> input = new ArrayList<String>();
		ArrayList<String> output = new ArrayList<String>();
		while(m.find())
		{
			input.add(m.group());
		}
		for(int i = 0; i<input.size()-5;i+=6)
		{
			//Since all the values are stored in the arraylist in order just take from the array list from 0-5 (there are 6 items.)
			String title = input.get(i);
			String body = input.get(i+1);
			String id = input.get(i+2);
			time = input.get(i+3);
			String g_loc = input.get(i+4);
			String s_loc = input.get(i+5);

			//Remove seperating colons and convert :: to :, from the title
			title = title.replaceAll("(?<!:):(?!:)","");
			title = title.replaceAll("::",":");

			//Remove separating colons and convert :: to :, from the body
			body = body.replaceAll("(?<!:):(?!:)","");
			body = body.replaceAll("::",":");

			//Remove separating colons from the id
			id = id.replaceAll(":","");

			//Remove separating colons and convert :: to :, from the time
			time = time.replaceAll("(?<!:):(?!:)","");
			time=time.replaceAll("::",":");

			//Remove separating colons and convert :: to :, from the general location
			g_loc = g_loc.replaceAll("(?<!:):(?!:)","");
			g_loc = g_loc.replaceAll("::",":");
			
			//Remove separating colons and convert :: to :, from the general location
			s_loc = s_loc.replaceAll("(?<!:):(?!:)","");
			s_loc = s_loc.replaceAll("::",":");
			
			//Now that the data has been cleaned put into the output arraylist
			output.add(title);
			output.add(body);
			output.add(id);
			output.add(time);
			output.add(g_loc);
			output.add(s_loc);
		}
		return output;
	}
	public void addTimeAlarm(long time)
	{
		AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
		Intent intent = new Intent(this, ReminderService.class);
		PendingIntent pendingIntent = PendingIntent.getService(this,0,intent,0);
		alarmManager.set(AlarmManager.RTC,time,pendingIntent);
	}
	public void addGenLocationAlarm(String loc,long id)
	{
		/*
		AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
		Intent intent = new Intent(this, GeneralService.class);
		intent.putExtra("search-string", loc);
		intent.putExtra("reminder-id",id);
		PendingIntent pendingIntent = PendingIntent.getService(this,0,intent,0);
		alarmManager.set(AlarmManager.RTC,System.currentTimeMillis(),pendingIntent);*/
		GeneralService.addItem(loc,id);
	}
	public void addSpecLocationAlarm(String loc, long id)
	{
		AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
		Intent intent = new Intent(this, SecificLocService.class);
		intent.putExtra("location", loc);
		intent.putExtra("reminder-id",id);
		PendingIntent pendingIntent = PendingIntent.getService(this,0,intent,0);
		alarmManager.set(AlarmManager.RTC,System.currentTimeMillis(),pendingIntent);
	}
	//Pulls Items from the server so that it can be added to local database
	public boolean retrieveItems()
	{
		Toast.makeText(this, "Checking for reminders...", 1).show();
		String time= "";
		long rtime = 0;
		ArrayList<Long> local = new ArrayList<Long>();
		Cursor temp = rDbHelper.fetchAllReminders();
		startManagingCursor(temp);
		if(temp!=null)
		{
			temp.moveToFirst();
			while(!temp.isAfterLast())
			{
				local.add(temp.getLong(3));
				temp.moveToNext();
			}
		}
		try{
			String response = HttpComm.executeHttpGet();
			ArrayList<String> input = new ArrayList<String>();
			input = parseServerInput(response);
			for(int i = 0; i<input.size()-5;i+=6)
			{
				String title = input.get(i);
				String body = input.get(i+1);
				String id = input.get(i+2);
				time = input.get(i+3);
				String g_loc = input.get(i+4);
				String s_loc = input.get(i+5);

				rtime=0;

				Cursor c = rDbHelper.fetchAllReminders();
				startManagingCursor(c);
				boolean add = true;
				if(c!=null)
				{
					c.moveToFirst();
					while(!c.isAfterLast())
					{
						if(c.getInt(3)==Integer.parseInt(id) )
						{
							add = false;
							break;
						}
						c.moveToNext();
					}
				}
				//calculate the timestamp based on the time-date sent
				if(!time.equals("0"))
					rtime = Timestamp.valueOf(time).getTime();
				//If it was not part of the local reminders then add alarm service.
				if(add == true)
				{
					//Obviously creates a reminder
					ReminderDbHelper.createReminder(title, body,Long.parseLong(id),rtime,g_loc, s_loc);
					
					//If there is a time reminder then set up the alarm service
					if(rtime>= (System.currentTimeMillis()))
					{
						addTimeAlarm(rtime);
					}
					//If there is a general reminder then set up the alarm service.
					if(!g_loc.equals(" ") && !g_loc.equals(""))
					{
						addGenLocationAlarm(g_loc,Long.parseLong(id));
					}
					if(!(s_loc.equals(LocationEditActivity.no_loc) || !s_loc.equals(" ") || !s_loc.equals("")))
					{
						addSpecLocationAlarm(s_loc, Long.parseLong(id));
					}
				}
				else
				{
					for(int x = 0; x<local.size();x++)
					{
						if(Long.parseLong(id) == local.get(x))
						{
							local.remove(x);
						}
					}
				}
			}
			while(local.size()>0)
			{
				if(temp!=null)
				{
					temp.moveToFirst();
					while(!temp.isAfterLast())
					{
						if(temp.getLong(3) == local.get(0))
						{
							try
							{
								HttpComm.executeHttpRemove(temp.getInt(3));
								rDbHelper.deleteReminder(temp.getLong(0));
								fillData();
								break;
							}
							catch(Exception e)
							{
								Toast.makeText(getApplicationContext(),e.toString(),1);
								return true;
							}
						}
						temp.moveToNext();
					}
				}
			}
		}
		catch(Exception e)
		{
			e.printStackTrace(System.out);
		}
		fillData();
		return true;
	}
	@Override
	public boolean onOptionsItemSelected(MenuItem item)
	{
		switch (item.getItemId()) 
		{
		case INSERT_ID:
			createReminder();
			break;
		case GET_ID:
			retrieveItems();
			break;
		case LOGOUT_ID:
			logout();
			break;
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) 
	{
		super.onCreateContextMenu(menu, v, menuInfo);
		menu.add(0, DELETE_ID, 0, R.string.menu_delete);
	}
	@Override
	public boolean onContextItemSelected(MenuItem item) 
	{
		switch(item.getItemId()) 
		{
		case DELETE_ID:
			AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
			Cursor c = rDbHelper.fetchReminder(info.id);
			try
			{
				HttpComm.executeHttpRemove(c.getInt(3));
				rDbHelper.deleteReminder(info.id);
				SecificLocService.removeReminder(info.id);
				fillData();
				System.out.println("Delete!!!");
				return true;
			}
			catch(Exception e)
			{
				e.printStackTrace(System.out);
			}
		}
		return super.onContextItemSelected(item);
	}
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent intent) 
	{
		super.onActivityResult(requestCode, resultCode, intent);
		if(intent !=null)
		{
			Bundle extras = intent.getExtras();
			switch(requestCode) 
			{
			case ACTIVITY_EDIT:
				Long rowId = extras.getLong(ReminderDbHelper.KEY_ROWID);
				if (rowId != null) 
				{
					String editTitle = extras.getString(ReminderDbHelper.KEY_TITLE);
					String editBody = extras.getString(ReminderDbHelper.KEY_BODY);
					String editGLoc = extras.getString(ReminderDbHelper.KEY_G_LOC);
					String editSLoc = extras.getString(ReminderDbHelper.KEY_S_LOC);
					String   editTime = extras.getString(ReminderDbHelper.KEY_TIME);
					Long   editRId  = extras.getLong(ReminderDbHelper.KEY_R_ID);
					long timestamp;
					if(!editTime.equals(""))
						timestamp = Timestamp.valueOf(editTime).getTime();
					else
						timestamp = 0;

					try{
						String response = HttpComm.executeHttpEdit(editRId,Uri.encode(editTitle),Uri.encode(editBody),editTime,Uri.encode(editGLoc),Uri.encode(editSLoc.split(":")[0]));
					}
					catch (Exception e)
					{
						System.out.println(e.getStackTrace());
					}
					rDbHelper.updateReminder(rowId, editTitle, editBody,editRId,timestamp,editGLoc,editSLoc);
				}
				fillData();
				break;
			case ACTIVITY_CREATE:
				add(intent);
				break;
			case ACTIVITY_MAP:
				switch(resultCode)
				{
				case RESULT_OK:
					if(extras != null)
					{
						setLoc(extras.getString(KEY_SELECTED_NAME), extras.getString(KEY_SELECTED_LOC));
					}
					break;
				}
				break;
			}
			fillData();
			
		}
	}
	private void add(Intent i)
	{
		Bundle extras = i.getExtras();
		//Retrieve data from the date and time pickers.
		String addTitle = extras.getString(ReminderDbHelper.KEY_TITLE);
		String addBody = extras.getString(ReminderDbHelper.KEY_BODY);
		String addGLoc = extras.getString(ReminderDbHelper.KEY_G_LOC);
		String preLimSLoc = extras.getString(ReminderDbHelper.KEY_S_LOC);
		String addTime = extras.getString(ReminderDbHelper.KEY_TIME);
		if (!preLimSLoc.equals("")){
			findAddr(preLimSLoc);
		}
		else
		{
			addSLoc="";
		}
		
		long timestamp;
		if(!addTime.equals(""))
			timestamp = Timestamp.valueOf(addTime).getTime();
		else
			timestamp = 0;
		try
		{
			//Send the add request to the server and get the response.
			String response = HttpComm.executeHttpAdd(Uri.encode(addTitle),Uri.encode(addBody),addTime,Uri.encode(addGLoc),Uri.encode(addSLoc.split(":")[0]));
			Pattern p = Pattern.compile("\\d+");
			Matcher m = p.matcher(response);
			ArrayList<String> input = new ArrayList<String>();
			while(m.find())
			{
				input.add(m.group());
			}
			if(input.size()>0)
			{
				ReminderDbHelper.createReminder(addTitle,addBody,Long.parseLong(input.get(0)),timestamp,addGLoc,addSLoc);
				if(timestamp>(System.currentTimeMillis()))
				{
					addTimeAlarm(timestamp);
				}
				if(!addGLoc.equals("") && !addGLoc.equals(" "))
				{
					addGenLocationAlarm(addGLoc,Long.parseLong(input.get(0)));
				}
				if(addSLoc!=null && !addSLoc.equals(LocationEditActivity.no_loc) && !addSLoc.equals("") && !addSLoc.equals(" "))
				{
					addSpecLocationAlarm(addSLoc,Long.parseLong(input.get(0)));
				}
			}
		}
		catch(Exception e)
		{
			System.out.println(e.toString());
		}
	}
	private void findAddr(String addr)
	{
		addr = addr.replaceAll("\\s", "%20");
		addr = addr.replaceAll(",", "");
		String tt = "";
		try
		{ 
			tt = HttpComm.executeHttpSpecAddr(addr);
		} 
		catch (Exception e) 
		{
			e.printStackTrace();
		}
		
		if(!tt.contains(":"))
			Toast.makeText(this, "No matches were found for location " + addr + ".", 1).show();
		else
		{
			String lst[] = tt.split(":");
			if(lst.length < 4)
			{
				setLoc(lst[0], lst[1]);
			}
			else
				start_map(tt);
		}
		
		
	}
	
	private void setLoc(String name, String loc)
	{
		String loc_gps = loc;
		String loc_name = name;
		String loc_str = loc_name + ":" + loc_gps;
		addSLoc = loc_str;
	}
	
	private void start_map(String entry)
	{
		Bundle extras = new Bundle();
		extras.putString(KEY_LIST_STRING, entry);
		Intent mIntent = new Intent(this, LocationSelectMap.class);
		
		mIntent.putExtras(extras);
		startActivityForResult(mIntent, ACTIVITY_MAP);
	}
	private void logout()
	{
		if(!HttpComm.logout())
			Toast.makeText(this, "Error: Couldn't log out.", 1).show();
		else
		{
			Toast.makeText(this, "Sucesfully logged out", 1).show();
			ReminderDbHelper.clearTable();
			finish();
	        startActivity(new Intent().setClass(this, LoginActivity.class));
		}
	}
}
